package com.proyecto.core.modelo.servicio;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.proyecto.core.Utilidades.ObtenerFecha;
import com.proyecto.core.Utilidades.UtilReflect;
import com.proyecto.core.Utilidades.UtilString;
import com.proyecto.core.Utilidades.UtilValidacion;
import com.proyecto.core.modelo.DAOGenerico;
import com.proyecto.core.modelo.HibernateTransaccion;
import com.proyecto.core.modelo.echo.constantes.TipoBusqueda;
import com.proyecto.core.modelo.excepciones.GeneralException;
import com.proyecto.core.modelo.servicio.interfaces.IServicioTransaccion;
import com.proyecto.core.modelo.validacion.IValidacionServicio;

@SuppressWarnings("all")
public class ServicioGenerico implements IServicioTransaccion {

	protected DAOGenerico propiedadDAO;

	protected IValidacionServicio validacion;

	protected String claveProperties;
	
	String rutaNombrePojo;
	
	boolean validacionActiva = true;
	
	public boolean iniciaTransacion=true;
	
	String rutaCiaOpr = "id.ciaopr";
	
	UtilValidacion utilValidacion = new UtilValidacion();
	
	protected HibernateTransactionManager transaccion;
	
	//public HibernateTransaccion trans;
	
	private TransactionStatus status;

	static final public int SERV_INCLUIR  	    = 1;
	static final public int SERV_MODIFICAR 		= 2;
	static final public int SERV_ELIMINAR       = 3;
	static final public int SERV_CONSULTAR      = 4;
	static final public int SERV_CONSULTARTODOS = 5;
	
	private ServicioTransaccion servicioTransaccion = new ServicioTransaccion();
	
	private Object servicioAuditoria;
	
	
	/**
	 * Metodo que recibe un objeto POJO, que se desea persistir, y una variable booleana para indicar
	 * si este servicio inicia una unidad de transaccion o si por el contrario esta dentro de una
	 * @author OpenLabs
	 * @param pojo: POJO a persistir
	 * @param iniciaTransaccion: Booleano que indica si con este servicio se inicia una transaccion o si es parte de una transaccion ya iniciada.
	 * @throws {@link GeneralException} propia(s) del(los) servicio(s) asociado(s) al(los) POJO(s) presente(s) en la transaccion. Pueden ser
	 *  ocacionadas por problemas de conexion, bloqueo optimista o error de acceso a la data.
	 * @return void
	 */
	public void incluir(Object pojo, boolean iniciaTransaccion) throws GeneralException {

		this.iniciaTransacion = iniciaTransaccion;
		
		if (isValidacionActiva()){
			validacion.incluir(pojo);
		}
		TransactionStatus status;
		status = this.iniciaTransacion?transaccion.getTransaction(new DefaultTransactionDefinition()):null;
		try {
			utilValidacion.verCambiaPorDefecto(pojo, propiedadDAO);
			if(servicioAuditoria!=null){
				this.llenarAuditoriaIncluir(pojo, servicioAuditoria);
			}
			propiedadDAO.save(pojo);
			if(status!=null){
				transaccion.commit(status);
				
			}
				
		} catch (org.springframework.dao.DataIntegrityViolationException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.PropertyValueException) {
				throw new GeneralException(
						"advertencia." + claveProperties + ".incluir.datoRequeridoVacio");
			} else if (e.getMostSpecificCause() instanceof ConstraintViolationException) {
				throw new GeneralException(
						"advertencia." + claveProperties + ".incluir.registroDuplicado");
			}
			throw new GeneralException("error." + claveProperties + ".incluir");

		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			e.printStackTrace();
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException(
						"error." + claveProperties + ".conexion");
			}
			throw new GeneralException("error." + claveProperties + ".incluir");
		} catch (Exception e) {
			try {
				transaccion.rollback(status);	
			}catch (Exception e1) {	
			}
			e.printStackTrace();
			throw new GeneralException(
					"error." + claveProperties + ".desconocido");
		}
	}
	/**
	 * Version BETA.. prueba usando transacciones.
	 * @param pojo
	 * @param s
	 * @throws GeneralException
	 * @author Carlos Yepez.
	 */
	public void incluir(Object pojo, Session s) throws GeneralException {
		
		Session sesion = null;
		Transaction t = null;
		if (isValidacionActiva() && null!=validacion){
			validacion.incluir(pojo);
		}
		try {
			utilValidacion.verCambiaPorDefecto(pojo, propiedadDAO);
			//Si recibe un Session null pido una conexion para hacer la transaccion atomica.
			if(s==null){
				sesion = propiedadDAO.getSessionFactory().openSession();
				t = sesion.beginTransaction();
				propiedadDAO.save(pojo,sesion);
				t.commit();
			}else{
				propiedadDAO.save(pojo, s);
			}
				
		} catch (org.springframework.dao.DataIntegrityViolationException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.PropertyValueException) {
				throw new GeneralException(
						"advertencia." + claveProperties + ".incluir.datoRequeridoVacio");
			} else if (e.getMostSpecificCause() instanceof ConstraintViolationException) {
				throw new GeneralException(
						"advertencia." + claveProperties + ".incluir.registroDuplicado");
			}
			throw new GeneralException("error." + claveProperties + ".incluir");

		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException(
						"error." + claveProperties + ".conexion");
			}
			throw new GeneralException("error." + claveProperties + ".incluir");
		} catch (Exception e) {
			try {
				transaccion.rollback(status);	
			}catch (Exception e1) {	
			}
			throw new GeneralException(
					"error." + claveProperties + ".desconocido");
		}finally{
			if(s==null){
				t = null;
				sesion.close();
				sesion = null;
			}
		}
	}
	
	/**
	 * Metodo que recibe y modifica un POJO, ya persistido.
	 * @param pojo: POJO persistido que se desea persistir
	 * @param iniciaTransaccion: Booleano que indica si la transaccion se inicia aca o si es parte de otra.
	 * @param iniciaTransaccion: Booleano que indica si con este servicio se inicia una transaccion o si es parte de una transaccion ya iniciada.
	 * @throws {@link GeneralException} propia(s) del(los) servicio(s) asociado(s) al(los) POJO(s) presente(s) en la transaccion. Pueden ser
	 *  ocacionadas por problemas de conexion, bloqueo optimista, error de acceso a la data, registro duplicado, ausencia de dato requerido
	 *  o problemas con inicio y cierre de la transaccion
	 * @return void
	 */
	public void modificar(Object pojo, boolean iniciaTransaccion) throws GeneralException {
/*
 		utilValidacion.verCambiaPorDefecto(pojo, propiedadDAO);			
		TransactionStatus status = transaccion.getTransaction(new DefaultTransactionDefinition());
		propiedadDAO.merge(pojo);
		transaccion.commit(status);
*/		
		if (isValidacionActiva()){
			validacion.modificar(pojo);
		}
		this.iniciaTransacion = iniciaTransaccion;
		TransactionStatus status;
		status = this.iniciaTransacion?transaccion.getTransaction(new DefaultTransactionDefinition()):null;
		try {
			utilValidacion.verCambiaPorDefecto(pojo, propiedadDAO);			
			propiedadDAO.merge(pojo);
			if(status!=null){
				transaccion.commit(status);
			}	
		}catch (org.springframework.dao.DataIntegrityViolationException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.PropertyValueException) {
				throw new GeneralException(
						"advertencia." + claveProperties + ".modificar.datoRequeridoVacio");
			} else if (e.getMostSpecificCause() instanceof ConstraintViolationException) {
				throw new GeneralException(
						"advertencia." + claveProperties + ".modificar.registroDuplicado");
			}
			throw new GeneralException(
					"error." + claveProperties + ".modificar");
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException(
						"error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".modificar");
		}catch (org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException hofe){
			//System.out.println("+++++++ clave: /"+"advertencia." + claveProperties + ".modificar.BloqueoOptimista"+"/");
			throw new GeneralException(
					"advertencia." + claveProperties + ".modificar.BloqueoOptimista");
		}
		catch (Exception e) {
			throw new GeneralException(
					"error." + claveProperties + ".desconocido");
		}
	}
	
	public void modificar(Object pojo, Session s) throws GeneralException {
		
		Session sesion = null;
		Transaction t = null;
		
		if (isValidacionActiva()){
//			validacios.modificar(pojo);
		}
		try {
			if(s==null){
				sesion = propiedadDAO.getSessionFactory().openSession();
				t = sesion.beginTransaction();
				propiedadDAO.merge(pojo, sesion);
				t.commit();
			}else{
				propiedadDAO.merge(pojo, s);
			}
			
			utilValidacion.verCambiaPorDefecto(pojo, propiedadDAO);			
			
			
			}catch (org.springframework.dao.DataIntegrityViolationException e) {
				if (e.getMostSpecificCause() instanceof org.hibernate.PropertyValueException) {
					throw new GeneralException(
							"advertencia." + claveProperties + ".modificar.datoRequeridoVacio");
				} else if (e.getMostSpecificCause() instanceof ConstraintViolationException) {
					throw new GeneralException(
							"advertencia." + claveProperties + ".modificar.registroDuplicado");
				}
					throw new GeneralException(
							"error." + claveProperties + ".modificar");
				} catch (org.springframework.dao.DataAccessResourceFailureException e) {
					if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
						throw new GeneralException(
								"error." + claveProperties + ".conexion");
				}
				throw new GeneralException(
							"error." + claveProperties + ".modificar");
				}catch (org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException hofe){
					//System.out.println("+++++++ clave: /"+"advertencia." + claveProperties + ".modificar.BloqueoOptimista"+"/");
					throw new GeneralException(
							"advertencia." + claveProperties + ".modificar.BloqueoOptimista");
				}
				catch (Exception e) {
					throw new GeneralException(
							"error." + claveProperties + ".desconocido");
				}finally{
					if(s == null){
						sesion.close();
						sesion = null;
					}
				}
			}
	
	/**
	 * Metodo que elimina un POJO ya persistido de la base de datos.
	 * @author OpenLabs
	 * @param pojo: POJO que se desea borrar de la base de datos.
	 * @param iniciaTransaccion: Booleano que indica si con este servicio se inicia una transaccion o si es parte de una transaccion ya iniciada.
	 * @throws {@link GeneralException} propia(s) del(los) servicio(s) asociado(s) al(los) POJO(s) presente(s) en la transaccion. Pueden ser
	 *  ocacionadas por problemas de conexion, bloqueo optimista o error de acceso a la data. 
	 * @return void.
	 */
	public void eliminar(Object pojo, boolean iniciaTransaccion) throws GeneralException {
		if (isValidacionActiva()){
			validacion.eliminar(pojo);
		}
		try {
			
			TransactionStatus status = transaccion.getTransaction(new DefaultTransactionDefinition());
			propiedadDAO.delete(pojo);
			transaccion.commit(status);
			
		} catch (org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.StaleStateException) {
				throw new GeneralException(
						"error." + claveProperties + ".eliminar.pkInvalida");
			}
			throw new GeneralException(
					"error." + claveProperties + ".eliminar");

		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException(
						"error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".eliminar");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".eliminar");
		} catch (Exception e) {
			System.err.println("e.getMessage():: " + e.getMessage()); 
			throw new GeneralException(
					"error." + claveProperties + ".desconocido");
		}
	}
	
	
public void eliminar(Object pojo, Session s) throws GeneralException {
		
		Session sesion = null;
		Transaction t = null;
		if (isValidacionActiva()){
			validacion.incluir(pojo);
		}
		try {
			utilValidacion.verCambiaPorDefecto(pojo, propiedadDAO);
			//Si recibe un Session null pido una conexion para hacer la transaccion atomica.
			if(s==null){
				sesion = propiedadDAO.getSessionFactory().openSession();
				t = sesion.beginTransaction();
				propiedadDAO.delete(pojo,sesion);
				t.commit();
			}else{
				propiedadDAO.delete(pojo, s);
			}
				
		} catch (org.springframework.dao.DataIntegrityViolationException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.PropertyValueException) {
				throw new GeneralException(
						"advertencia." + claveProperties + ".incluir.datoRequeridoVacio");
			} else if (e.getMostSpecificCause() instanceof ConstraintViolationException) {
				throw new GeneralException(
						"advertencia." + claveProperties + ".incluir.registroDuplicado");
			}
			throw new GeneralException("error." + claveProperties + ".incluir");

		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException(
						"error." + claveProperties + ".conexion");
			}
			throw new GeneralException("error." + claveProperties + ".incluir");
		} catch (Exception e) {
			try {
				transaccion.rollback(status);	
			}catch (Exception e1) {	
			}
			throw new GeneralException(
					"error." + claveProperties + ".desconocido");
		}finally{
			if(s==null){
				t = null;
				sesion.close();
				sesion = null;
			}
		}
	}
	
	
	
	public Object consultar(Object o) throws GeneralException {
		if (isValidacionActiva()){
			validacion.consultar(o);
		}
		
		Object obj = null;
		try {
			obj = propiedadDAO.findById(o);
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException("error." + claveProperties + ".consulta");

		} catch (Exception e) {
			throw new GeneralException("error." + claveProperties + ".desconocido");
		}
		if (obj == null) {
			throw new GeneralException("advertencia." + claveProperties + ".consulta.consultaVacia");
		}
		return obj;
	}

	
	/**
	 * Consutar que utiliza sesion
	 * */
	public Object consultar(Object o, Session s) throws GeneralException {
		Session sesion = null;
		Transaction t = null;
		if(s==null){//Si la sesion que recibo es nula
			sesion = propiedadDAO.getSessionFactory().openSession();//Obtengo una sesion
			t = sesion.beginTransaction();//Inicio la transaccion
		}else{//Si recibo la sesion, la uso
			sesion = s;
		}
		if (isValidacionActiva()&& null!=validacion){
			validacion.consultar(o);
		}
		
		Object obj = null;
		try {
			obj = propiedadDAO.findById(o, sesion);
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException("error." + claveProperties + ".consulta");

		} catch (Exception e) {
			throw new GeneralException("error." + claveProperties + ".desconocido");
		}finally{
			if(s == null){//Si no recibi la transaccion
				t.commit();//Commit a la transaccion
				sesion.close();//Cierro la sesion
				sesion=null;//Inicializo el valor de la sesion
				t= null;//Inicializo el valor de la transaccion
			}
		}
		if (obj == null) {
			throw new GeneralException("advertencia." + claveProperties + ".consulta.consultaVacia");
		}
		return obj;
	}
	
	public List consultarTodos(Object o) throws GeneralException {
		if (isValidacionActiva()){
			validacion.consultarTodos(o);
		}
		List list = null;
		try {
			list = propiedadDAO.findByProperty(this.rutaCiaOpr, o);
			
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".consulta");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".consulta");
		} catch (Exception e) {
			throw new GeneralException(
					"error." + claveProperties + ".desconocido");
		}
		if (list.size() == 0) {
			throw new GeneralException(
					"advertencia." + claveProperties + ".consulta.consultaVacia");
		}
		return list;
	}
	
	public List consultarTodosPorRangos(Object o, int limiteInferior, int limiteSuperior) throws GeneralException {
		if (isValidacionActiva()){
			validacion.consultarTodos(o);
		}
		List list = null;
		try {
			list = propiedadDAO.findByPropertyPorRango(this.rutaCiaOpr, o, limiteInferior, limiteSuperior);
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".consulta");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".consulta");
		} catch (Exception e) {
			throw new GeneralException(
					"error." + claveProperties + ".desconocido");
		}
		if (list.size() == 0) {
			throw new GeneralException(
					"advertencia." + claveProperties + ".consulta.consultaVacia");
		}
		return list;
	}
	
	public List buscarCatalogoPorPropiedad(String[] atributo, Object[] valor, int tipoBusqueda,boolean ... aplicarUpper) throws GeneralException {
//		 validacion.buscarCatalogoPorPropiedad(atributo, valor);
		List list = null;
		try {
			list = this.propiedadDAO.buscarPorPropiedad(atributo, valor,
					tipoBusqueda,aplicarUpper);
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (Exception e) {
			if (("advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia").equals(e.getMessage())){
				throw new GeneralException(e.getMessage());
			} else {
				throw new GeneralException("error." + claveProperties + ".desconocido");
			}	
		}
		
		if (list.size() == 0) {			
			throw new GeneralException(
					"advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia");
		}
		
		return list;
	}
	
	public int buscarCatalogoPorPropiedadCount(String[] atributo, Object[] valor, int tipoBusqueda,boolean ... aplicarUpper) throws GeneralException {
		int resultado;
		try {
			resultado = this.propiedadDAO.buscarPorPropiedadCount(atributo, valor,
					tipoBusqueda,aplicarUpper);
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (Exception e) {
			if (("advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia").equals(e.getMessage())){
				throw new GeneralException(e.getMessage());
			} else {
				throw new GeneralException("error." + claveProperties + ".desconocido");
			}	
		}
		
		return resultado;
	}

	public int buscarCatalogoPorPropiedadCount(String[] atributo, Object[] valor, int tipoBusqueda, int condicionFiltro, boolean ... aplicarUpper) throws GeneralException {
		int resultado;
		try {
			resultado = this.propiedadDAO.buscarPorPropiedadCount(atributo, valor,
					tipoBusqueda,condicionFiltro,aplicarUpper);
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (Exception e) {
			if (("advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia").equals(e.getMessage())){
				throw new GeneralException(e.getMessage());
			} else {
				throw new GeneralException("error." + claveProperties + ".desconocido");
			}	
		}
		
		return resultado;
	}

	public int buscarCatalogoPorPropiedadCountEspecialMedicamento(String[] atributo, Object[] valor, int tipoBusqueda, int condicionFiltro, boolean ... aplicarUpper) throws GeneralException {
		int resultado;
		try {
			resultado = this.propiedadDAO.buscarPorPropiedadCountEspecialMedicamento(atributo, valor,
					tipoBusqueda,condicionFiltro,aplicarUpper);
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (Exception e) {
			if (("advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia").equals(e.getMessage())){
				throw new GeneralException(e.getMessage());
			} else {
				throw new GeneralException("error." + claveProperties + ".desconocido");
			}	
		}
		
		return resultado;
	}
	
	public List buscarCatalogoPorPropiedadPorRangos(String[] atributo, Object[] valor,int limiteInferior, int limiteSuperiro, int tipoBusqueda, boolean ... aplicarUpper) throws GeneralException {
		List list = null;
		try {
			list = this.propiedadDAO.buscarPorPropiedadPorRangos(atributo, valor,limiteInferior,limiteSuperiro,
					tipoBusqueda,aplicarUpper);
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (Exception e) {
			if (("advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia").equals(e.getMessage())){
				throw new GeneralException(e.getMessage());
			} else {
				throw new GeneralException("error." + claveProperties + ".desconocido");
			}	
		}
		
		if (list.size() == 0) {			
			throw new GeneralException(
					"advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia");
		}
		
		return list;
	}

	public List buscarCatalogoPorPropiedadPorRangos(String[] atributo, Object[] valor,int limiteInferior, int limiteSuperiro, 
												int tipoBusqueda, int condicionFiltro, boolean ... aplicarUpper) throws GeneralException {
		List list = null;
		try {
			list = this.propiedadDAO.buscarPorPropiedadPorRangos(atributo, valor,limiteInferior,limiteSuperiro,
					tipoBusqueda,condicionFiltro,aplicarUpper);
			//System.out.println("list.size:" + list.size());
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (Exception e) {
			if (("advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia").equals(e.getMessage())){
				throw new GeneralException(e.getMessage());
			} else {
				throw new GeneralException("error." + claveProperties + ".desconocido");
			}	
		}
		
		if (list.size() == 0) {			
			throw new GeneralException(
					"advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia");
		}
		
		return list;
	}

	public List buscarCatalogoPorPropiedadPorRangosEspecialMedicamento(String[] atributo, Object[] valor,int limiteInferior, int limiteSuperiro, 
												int tipoBusqueda, int condicionFiltro, boolean ... aplicarUpper) throws GeneralException {
		List list = null;
		try {
			list = this.propiedadDAO.buscarPorPropiedadPorRangosEspecialMedicamento(atributo, valor,limiteInferior,limiteSuperiro,
					tipoBusqueda,condicionFiltro,aplicarUpper);
			//System.out.println("list.size:" + list.size());
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (Exception e) {
			if (("advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia").equals(e.getMessage())){
				throw new GeneralException(e.getMessage());
			} else {
				throw new GeneralException("error." + claveProperties + ".desconocido");
			}	
		}
		
		if (list.size() == 0) {			
			throw new GeneralException(
					"advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia");
		}
		
		return list;
	}
	public void ejecutarQueryDMLk(String query, Session s) throws GeneralException{
		
		try{
			propiedadDAO.ejecutarQuerySession(query,s);
		}catch (Exception e) {
			if (e instanceof ConstraintViolationException) {
				GeneralException ge = new GeneralException("error." + claveProperties + ".constrainviolations");
				ge.setExcepcion(e);
				throw ge;
			}
		}
	}
	
	public void EjecutarServicioSinValid(Object o, Integer servicio) throws GeneralException {
	
		boolean estadoanterior = this.isValidacionActiva();
		setValidacionActiva(false);

		switch (servicio) {
		case ServicioGenerico.SERV_INCLUIR:
			this.incluir(o,true);
			break;
		case ServicioGenerico.SERV_MODIFICAR:
			this.modificar(o,true);
			break;
		case ServicioGenerico.SERV_ELIMINAR:
			this.eliminar(o,true);
			break;
		case ServicioGenerico.SERV_CONSULTAR:
			this.consultar(o);
			break;
		case ServicioGenerico.SERV_CONSULTARTODOS:
			this.consultarTodos(o);
			break;
		default:
			break;
		}
		setValidacionActiva(estadoanterior);
	}
	
	
	public int buscarCatalogoPorPropiedadMultiPaseCount(String[] atributo, Object[] valor, int[] tipoBusqueda,boolean ... aplicarUpper) throws GeneralException {
		int resultado;
		try {
			resultado = this.propiedadDAO.buscarPorPropiedadMultiPaseCount(atributo, valor,
					tipoBusqueda,aplicarUpper);
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (Exception e) {
			if (("advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia").equals(e.getMessage())){
				throw new GeneralException(e.getMessage());
			} else {
				System.err.println("e.buscarCatalogoPorPropiedadMultiPaseCount:: " + e.getMessage() );
				throw new GeneralException("error." + claveProperties + ".desconocido");
			}
		}
		
		return resultado;
	}
	

	public List buscarCatalogoPorPropiedadMultiPase(String[] atributo, Object[] valor, int[] tipoBusqueda,boolean ... aplicarUpper) throws GeneralException {
//		 validacion.buscarCatalogoPorPropiedad(atributo, valor);
		List list = null;
		try {
			list = this.propiedadDAO.buscarPorPropiedadMultiPase(atributo, valor,
					tipoBusqueda,aplicarUpper);
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (Exception e) {
			if (("advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia").equals(e.getMessage())){
				throw new GeneralException(e.getMessage());
			} else {
				throw new GeneralException("error." + claveProperties + ".desconocido");
			}	
		}
		
		if (list.size() == 0) {			
			throw new GeneralException(
					"advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia");
		}
		
		return list;
	}

	
	public void EjecutarServicioSinValid(Object o, Integer servicio, Session s) throws GeneralException {
		
		boolean estadoanterior = this.isValidacionActiva();
		setValidacionActiva(false);

		switch (servicio) {
		case ServicioGenerico.SERV_INCLUIR:
			this.incluir(o,s);
			break;
		case ServicioGenerico.SERV_MODIFICAR:
			this.modificar(o,s);
			break;
		case ServicioGenerico.SERV_ELIMINAR:
			this.eliminar(o,true);
			break;
		case ServicioGenerico.SERV_CONSULTAR:
			this.consultar(o,s);
			break;
		case ServicioGenerico.SERV_CONSULTARTODOS:
			this.consultarTodos(o);
			break;
		default:
			break;
		}
		setValidacionActiva(estadoanterior);
	}
	
	public Object obtenerDTOInicianlizado() throws GeneralException {		
		Object pojo = null;
		try {
			Class clase = Class.forName(rutaNombrePojo);
			pojo = clase.newInstance();
		} catch (ClassNotFoundException e) {
		} catch (InstantiationException e) {
		} catch (IllegalAccessException e) {
		}
		return pojo;
	}
	
	public Session iniciarTransaccion() throws GeneralException{
		Session sesion = servicioTransaccion.iniciarTransaccion();
		return sesion;
	}
	
	public void finalizarTransaccion() throws GeneralException{
		servicioTransaccion.finalizarTransaccion();
	}
	
	public void reversarTransaccion(){
		servicioTransaccion.reversarTransaccion();
	}

	public IValidacionServicio getValidacion() {
		return validacion;
	}

	public void setValidacion(IValidacionServicio validacion) {
		this.validacion = validacion;
	}

	public DAOGenerico getPropiedadDAO() {
		return propiedadDAO;
	}

	public void setPropiedadDAO(DAOGenerico propiedadDAO) {
		this.propiedadDAO = propiedadDAO;
		servicioTransaccion.setSesionFactory(propiedadDAO.getSessionFactory());
	}

	public String getClaveProperties() {
		return claveProperties;
	}

	public void setClaveProperties(String claveProperties) {
		this.claveProperties = claveProperties;
	}

	public String getRutaNombrePojo() {
		return rutaNombrePojo;
	}

	public void setRutaNombrePojo(String rutaNombrePojo) {
		this.rutaNombrePojo = rutaNombrePojo;
		try {
			propiedadDAO.setClase(Class.forName(rutaNombrePojo));
		} catch (ClassNotFoundException e) {
		}
	}

	public String getRutaCiaOpr() {
		return rutaCiaOpr;
	}

	public void setRutaCiaOpr(String rutaCiaOpr) {
		this.rutaCiaOpr = rutaCiaOpr;
	}

	public UtilValidacion getUtilValidacion() {
		return utilValidacion;
	}

	public void setUtilValidacion(UtilValidacion utilValidacion) {
		this.utilValidacion = utilValidacion;
	}

	public boolean isValidacionActiva() {
		return validacionActiva;
	}

	public void setValidacionActiva(boolean validacionActiva) {
		this.validacionActiva = validacionActiva;
	}

	/**
	 * BUSCAMSO EL DATO MAXIMO dentre los registros filtraos en los 2 primeros parametros
	 * los parametros atributo y valor estan en funcion del where.
	 * el parametro atributoMax es para incluirlo en el select Max(dato) para identificar cual es el maximo dato segun el registro con filtro del where.
	 * 
	 * @param atributo
	 * @param valor
	 * @param atributoMax
	 * @param tipoBusqueda
	 * @return
	 * @throws GeneralException
	 */
	public Integer buscarMaxDatos(String[] atributo, Object[] valor, String atributoMax,int tipoBusqueda) throws GeneralException {
		List list = null;
		try {
			list = this.propiedadDAO.maxBusqueda(atributo, valor, atributoMax, tipoBusqueda,true);
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
				if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
					throw new GeneralException("error." + claveProperties + ".conexion");
				}
				throw new GeneralException(
						"error." + claveProperties + ".buscarCatalogoXPropiedad");
			} catch (org.springframework.dao.DataAccessException e) {
				throw new GeneralException(
						"error." + claveProperties + ".buscarCatalogoXPropiedad");
			} catch (Exception e) {
				if (("advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia").equals(e.getMessage())){
					throw new GeneralException(e.getMessage());
				} else {
					throw new GeneralException("error." + claveProperties + ".desconocido");
				}	
			}
			
			if (list.size() == 0) {
				throw new GeneralException(
						"advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia");
			}
				
		return Integer.parseInt(list.get(0).toString());
	}
	
	public Long buscarMaxCount(String[] atributo, Object[] valor, int tipoBusqueda) throws GeneralException {
		List list = null;
		try {
			list = this.propiedadDAO.countBusqueda(atributo, valor,
					tipoBusqueda);
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (Exception e) {
			if (("advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia").equals(e.getMessage())){
				throw new GeneralException(e.getMessage());
			} else {
				throw new GeneralException("error." + claveProperties + ".desconocido");
			}	
		}
		
		if (list.size() == 0) {
			throw new GeneralException(
					"advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia");
		}
		
		return Long.parseLong(list.get(0).toString());
	}

	public Long buscarMaxCount(String[] atributo, Object[] valor, int condicionFiltro, int tipoBusqueda) throws GeneralException {
		List list = null;
		try {
			list = this.propiedadDAO.countBusqueda(atributo, valor,
					condicionFiltro, tipoBusqueda);
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (Exception e) {
			if (("advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia").equals(e.getMessage())){
				throw new GeneralException(e.getMessage());
			} else {
				throw new GeneralException("error." + claveProperties + ".desconocido");
			}	
		}
		
		if (list.size() == 0) {
			throw new GeneralException(
					"advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia");
		}
		
		return Long.parseLong(list.get(0).toString());
	}

	public Long buscarMaxCountEspecialMedicamento(String[] atributo, Object[] valor, int condicionFiltro, int tipoBusqueda) throws GeneralException {
		List list = null;
		try {
			list = this.propiedadDAO.countBusquedaEspecialMedicamento(atributo, valor,
					condicionFiltro, tipoBusqueda);
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".buscarCatalogoXPropiedad");
		} catch (Exception e) {
			if (("advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia").equals(e.getMessage())){
				throw new GeneralException(e.getMessage());
			} else {
				throw new GeneralException("error." + claveProperties + ".desconocido");
			}	
		}
		
		if (list.size() == 0) {
			throw new GeneralException(
					"advertencia." + claveProperties + ".buscarCatalogoXPropiedad.consultaVacia");
		}
		
		return Long.parseLong(list.get(0).toString());
	}
	
	public List ejecutarQueryHQL(String query) throws GeneralException {
		List list = null;
		try {
			list = propiedadDAO.ejecutarQueryConsulta(query);
		} catch (org.springframework.dao.DataAccessResourceFailureException e) {
			if (e.getMostSpecificCause() instanceof org.hibernate.exception.JDBCConnectionException) {
				throw new GeneralException("error." + claveProperties + ".conexion");
			}
			throw new GeneralException(
					"error." + claveProperties + ".consulta");
		} catch (org.springframework.dao.DataAccessException e) {
			throw new GeneralException(
					"error." + claveProperties + ".consulta");
		} catch (Exception e) {
			throw new GeneralException(
					"error." + claveProperties + ".desconocido");
		}
		if (list.size() == 0) {
			throw new GeneralException(
					"advertencia." + claveProperties + ".consulta.consultaVacia");//TODO Colocar en propetie consultaHQL
		}
		return list;
	}
	
	public String numeroString(Long numero, String formato){
		String numeroString = "";
		if (!UtilString.esVacio(formato)){
			Integer longigutNumero  = numero.toString().trim().length();
			numeroString = formato.substring(longigutNumero) + numero.toString();
		}else {
			numeroString = numero.toString();
		}
		return numeroString;
	}
	
	public String recontruirFormato(String prefijo, String formato){
		String formatoString = "";
		if (!UtilString.esVacio(formato)){
			Integer longigutNumero  = prefijo.toString().trim().length();
			formatoString = prefijo.toString() + formato.substring(longigutNumero);
		}else {
			formatoString = prefijo.toString();
		}
		System.out.println("formatoString::: " + formatoString);
		return formatoString;
	}
	
	public String numeroStringRecontruidoPorFormato(String correlativoString, String prefijo){
		String numeroString = "";
		if (!UtilString.esVacio(prefijo)){
			Integer longigutNumero  = prefijo.toString().trim().length();
			//System.out.println("longigutNumero.numero::: " + longigutNumero);
			//System.out.println("correlativoString.substring(longigutNumero)::: " + correlativoString.substring(longigutNumero));
			numeroString = prefijo + correlativoString.substring(longigutNumero);
		}else {
			numeroString = correlativoString.toString();
		}
		return numeroString;
	}
	
	private void llenarAuditoriaIncluir(Object pojo, Object segUsuario){
		try {
			String usuariocod = UtilReflect.invocarMetodoGetSet(true,segUsuario,"segUsuarios.id.usuariocodigo", 
					  null,null).toString();
			UtilReflect.invocarMetodoGetSet(false,pojo,"auditcodusuario",new Class[] {String.class},usuariocod);
			UtilReflect.invocarMetodoGetSet(false,pojo,"auditfechacreacion",new Class[] {String.class},ObtenerFecha.ObtenerFechaSistemaYYYYMMDD());
			UtilReflect.invocarMetodoGetSet(false,pojo,"audithoracreacion",new Class[] {String.class},ObtenerFecha.ObtenerHoraSistema());
			
		} catch (Exception e) {
			System.err.println("NO SE ESTAN LLENANDO LOS CAMPOS DE AUDITORIA PARA ESTA OPERACION... <POJO "+pojo.getClass().getSimpleName()+"> INCLUIR");
		} 
	}
	
	private void llenarAuditoriaModificar(Object pojo, Object segUsuario){
		try {
			String usuariocod = UtilReflect.invocarMetodoGetSet(true,segUsuario,"segUsuarios.id.usuariocodigo", 
					  null,null).toString();
			UtilReflect.invocarMetodoGetSet(false,pojo,"auditcodusuario",new Class[] {String.class},usuariocod);
			UtilReflect.invocarMetodoGetSet(false,pojo,"auditfechacambio",new Class[] {String.class},ObtenerFecha.ObtenerFechaSistemaYYYYMMDD());
			UtilReflect.invocarMetodoGetSet(false,pojo,"audithoracambio",new Class[] {String.class},ObtenerFecha.ObtenerHoraSistema());
			
		} catch (Exception e) {
			System.err.println("NO SE ESTAN LLENANDO LOS CAMPOS DE AUDITORIA PARA ESTA OPERACION... <POJO "+pojo.getClass().getSimpleName()+"> MODIFICAR");
		} 
	}
	
	public HibernateTransactionManager getTransaccion() {
		return transaccion;
	}

	public void setTransaccion(HibernateTransactionManager transaccion) {
		this.transaccion = transaccion;
	}

	public boolean isIniciaTransacion() {
		return iniciaTransacion;
	}

	public void setIniciaTransacion(boolean iniciaTransacion) {
		this.iniciaTransacion = iniciaTransacion;
	}

	public ServicioGenerico() {
		super();
	}

	public Object ejecutarMetodo(String nombreMetodo, Object[] arregloParametros) throws GeneralException {
		return null;
	}
	public Object getServicioAuditoria() {
		return servicioAuditoria;
	}
	public void setServicioAuditoria(Object servicioAuditoria) {
		this.servicioAuditoria = servicioAuditoria;
	}
	
}
